package devcken.springframework.core.convert.converter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;

/**
 * HTTP 요청으로 들어오는 파라메터 중, 형식에 일치하는 파라메터를 {@link java.util.Date Date} 인스턴스로 자동 변환해주는 {@link org.springframework.core.convert.converter.Converter Converter}를 구현한다.
 * {@link devcken.text.DateTimeFormatter DateTimeFormatter}와 다른 점은 HTTP 요청으로 들어오는 파라메터를 변환해주는 전략으로써 사용된다는 점이다.
 * @author Devcken
 */
public final class DateConverter<T extends Date> implements Converter<String, T>
{
	private final static Logger logger = LoggerFactory.getLogger(DateConverter.class);
	
	/**
	 * 기본 날짜/시간 형식을 나타낸다.
	 */
	private DateFormat _defaultDateFormat;
	
	/**
	 * 추가 날짜/시간 형식을 나타낸다.
	 */
	private DateFormat[] _acceptableFormats;
	
	public DateConverter()
	{
	}

	@Override
	public T convert(String parameter)
	{
		if (parameter.length() == 0)
		{
			return null;
		}
		
		return this.parse(parameter);
	}
	
	/**
	 * 파라메터가 형식에 맞는 경우 {@link java.util.Date Date} 인스턴스로 변환한다. 
	 * @param parameter HTTP 요청에 포함된 파라메터가 전달된다.
	 * @return 변환된 {@link java.util.Date Date} 인스턴스를 반환한다.
	 */
	@SuppressWarnings("unchecked")
	public T parse(String parameter)
	{
		try
		{
			// 파라메터를 변환하여 기본 날짜 형식에 맞는지 검사한다. 
			if (this._defaultDateFormat != null)
			{
				try
				{
					T result = (T)this._defaultDateFormat.parse(parameter);
					
					if (result != null && parameter.equals(this._defaultDateFormat.format(result)))
					{
						return result;
					}
				}
				catch (Exception error)
				{
					logger.error(error.getMessage(), error);
				}
			}
			
			// 기본 날짜 형식 이외의 추가 형식에 맞는 검사하여 파라메터를 변환한다.
			if (this._acceptableFormats != null)
			{
				for (int index = 0; index < this._acceptableFormats.length; index++)
				{
					T result = null;
					
					try
					{
						result = (T)this._acceptableFormats[index].parse(parameter);
						
						if (result != null && parameter.equals(this._acceptableFormats[index].format(result)))
						{
							return result;
						}
					}
					catch (Exception error)
					{
						logger.error(error.getMessage(), error);
						
						continue;
					}
				}
			}
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return null;
	}
	
	/**
	 * 기본 날짜 형식을 설정한다.
	 * @param defaultDateFormat 기본 날짜 형식을 설정한다.
	 */
	public void setDefaultDateFormat(String defaultDateFormat)
	{
		try
		{
			this._defaultDateFormat = new SimpleDateFormat(defaultDateFormat);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
	}
	
	/**
	 * 추가 날짜 형식을 설정한다.
	 * @param acceptableFormats 추가 날짜 형식을 설정한다.
	 */
	public void setAcceptableFormats(String[] acceptableFormats)
	{
		try
		{
			this._acceptableFormats = new SimpleDateFormat[acceptableFormats.length];
			
			for (int index = 0; index < acceptableFormats.length; index++)
			{
				this._acceptableFormats[index] = new SimpleDateFormat(acceptableFormats[index]);
			}
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
	}
}